package com.datagateway.component;

import org.apache.camel.CamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 优雅关闭管理器
 * 负责在应用停止时安全处理剩余数据
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class GracefulShutdownManager implements ApplicationListener<ContextClosedEvent> {

    private static final Logger logger = LoggerFactory.getLogger(GracefulShutdownManager.class);

    @Autowired
    private CamelContext camelContext;

    @Autowired
    private DataBuffer dataBuffer;

    @Autowired
    private RetryQueue retryQueue;

    @Autowired
    private AlertManager alertManager;

    /**
     * 关闭状态标志
     */
    private final AtomicBoolean isShuttingDown = new AtomicBoolean(false);

    /**
     * 关闭完成信号
     */
    private final CountDownLatch shutdownLatch = new CountDownLatch(1);

    /**
     * 最大等待时间（秒）
     */
    private static final int MAX_SHUTDOWN_WAIT_SECONDS = 60;

    /**
     * 应用关闭事件处理
     * 
     * @param event 上下文关闭事件
     */
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        if (isShuttingDown.compareAndSet(false, true)) {
            logger.info("开始优雅关闭流程...");
            
            try {
                // 执行优雅关闭流程
                performGracefulShutdown();
                
                logger.info("优雅关闭流程完成");
            } catch (Exception e) {
                logger.error("优雅关闭过程中发生异常", e);
            } finally {
                shutdownLatch.countDown();
            }
        }
    }

    /**
     * 执行优雅关闭流程
     */
    private void performGracefulShutdown() {
        try {
            // 1. 停止接收新数据
            stopAcceptingNewData();
            
            // 2. 停止Camel路由
            stopCamelRoutes();
            
            // 3. 处理剩余数据
            processRemainingData();
            
            // 4. 清理资源
            cleanupResources();
            
            // 5. 发送关闭通知
            sendShutdownNotification();
            
        } catch (Exception e) {
            logger.error("优雅关闭流程执行失败", e);
            throw e;
        }
    }

    /**
     * 停止接收新数据
     */
    private void stopAcceptingNewData() {
        logger.info("停止接收新数据...");
        
        try {
            // 这里可以设置标志位，让数据接收组件停止处理新数据
            // 由于我们使用的是Camel路由，停止路由会自动停止接收新数据
            
            logger.info("已停止接收新数据");
        } catch (Exception e) {
            logger.error("停止接收新数据失败", e);
        }
    }

    /**
     * 停止Camel路由
     */
    private void stopCamelRoutes() {
        logger.info("停止Camel路由...");
        
        try {
            if (camelContext != null && camelContext.getStatus().isStarted()) {
                // 优雅停止Camel上下文
                camelContext.stop();
                
                // 等待路由完全停止
                int waitTime = 0;
                while (camelContext.getStatus().isStarted() && waitTime < 30) {
                    Thread.sleep(1000);
                    waitTime++;
                }
                
                if (camelContext.getStatus().isStarted()) {
                    logger.warn("Camel路由停止超时，强制停止");
                    camelContext.stop();
                }
            }
            
            logger.info("Camel路由已停止");
        } catch (Exception e) {
            logger.error("停止Camel路由失败", e);
        }
    }

    /**
     * 处理剩余数据
     */
    private void processRemainingData() {
        logger.info("处理剩余数据...");
        
        try {
            // 1. 刷新数据缓冲区
            flushDataBuffer();
            
            // 2. 处理重试队列
            processRetryQueue();
            
            // 3. 等待处理完成
            waitForProcessingComplete();
            
            logger.info("剩余数据处理完成");
        } catch (Exception e) {
            logger.error("处理剩余数据失败", e);
        }
    }

    /**
     * 刷新数据缓冲区
     */
    private void flushDataBuffer() {
        logger.info("刷新数据缓冲区...");
        
        try {
            if (dataBuffer != null) {
                dataBuffer.flush();
                logger.info("数据缓冲区已刷新");
            }
        } catch (Exception e) {
            logger.error("刷新数据缓冲区失败", e);
        }
    }

    /**
     * 处理重试队列
     */
    private void processRetryQueue() {
        logger.info("处理重试队列...");
        
        try {
            if (retryQueue != null) {
                // 获取重试队列统计
                var retryStats = retryQueue.getRetryStatistics();
                
                if (retryStats.getRetryQueueSize() > 0) {
                    logger.info("重试队列中还有 {} 条数据，等待处理完成", retryStats.getRetryQueueSize());
                    
                    // 等待重试队列处理完成
                    int waitTime = 0;
                    while (retryStats.getRetryQueueSize() > 0 && waitTime < 30) {
                        Thread.sleep(1000);
                        retryStats = retryQueue.getRetryStatistics();
                        waitTime++;
                    }
                    
                    if (retryStats.getRetryQueueSize() > 0) {
                        logger.warn("重试队列处理超时，剩余 {} 条数据", retryStats.getRetryQueueSize());
                    }
                }
                
                logger.info("重试队列处理完成");
            }
        } catch (Exception e) {
            logger.error("处理重试队列失败", e);
        }
    }

    /**
     * 等待处理完成
     */
    private void waitForProcessingComplete() {
        logger.info("等待数据处理完成...");
        
        try {
            // 等待一段时间让所有异步任务完成
            Thread.sleep(5000);
            
            // 这里可以添加更精确的等待逻辑
            // 例如：检查线程池状态、队列大小等
            
            logger.info("数据处理等待完成");
        } catch (InterruptedException e) {
            logger.warn("等待处理完成时被中断", e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 清理资源
     */
    private void cleanupResources() {
        logger.info("清理系统资源...");
        
        try {
            // 1. 清理缓存
            cleanupCaches();
            
            // 2. 关闭数据库连接
            closeDatabaseConnections();
            
            // 3. 清理临时文件
            cleanupTempFiles();
            
            logger.info("系统资源清理完成");
        } catch (Exception e) {
            logger.error("清理系统资源失败", e);
        }
    }

    /**
     * 清理缓存
     */
    private void cleanupCaches() {
        logger.info("清理系统缓存...");
        
        try {
            // 清理Groovy脚本缓存
            // groovyScriptEngine.clearCache();
            
            // 清理分区缓存
            // partitionManager.cleanupExpiredPartitions(0);
            
            logger.info("系统缓存清理完成");
        } catch (Exception e) {
            logger.error("清理系统缓存失败", e);
        }
    }

    /**
     * 关闭数据库连接
     */
    private void closeDatabaseConnections() {
        logger.info("关闭数据库连接...");
        
        try {
            // 这里可以添加关闭数据库连接的逻辑
            // 由于我们使用的是Spring Boot的自动配置，连接池会自动关闭
            
            logger.info("数据库连接已关闭");
        } catch (Exception e) {
            logger.error("关闭数据库连接失败", e);
        }
    }

    /**
     * 清理临时文件
     */
    private void cleanupTempFiles() {
        logger.info("清理临时文件...");
        
        try {
            // 清理临时文件
            // 这里可以添加清理临时文件的逻辑
            
            logger.info("临时文件清理完成");
        } catch (Exception e) {
            logger.error("清理临时文件失败", e);
        }
    }

    /**
     * 发送关闭通知
     */
    private void sendShutdownNotification() {
        logger.info("发送关闭通知...");
        
        try {
            if (alertManager != null) {
                alertManager.sendAlert(
                    AlertManager.AlertLevel.INFO,
                    AlertManager.AlertType.SYSTEM_ERROR,
                    "系统关闭通知",
                    "数据网关系统正在优雅关闭",
                    "系统将在完成剩余数据处理后完全关闭"
                );
            }
            
            logger.info("关闭通知已发送");
        } catch (Exception e) {
            logger.error("发送关闭通知失败", e);
        }
    }

    /**
     * 等待关闭完成
     * 
     * @param timeoutSeconds 超时时间（秒）
     * @return true如果关闭完成
     */
    public boolean waitForShutdownComplete(int timeoutSeconds) {
        try {
            return shutdownLatch.await(timeoutSeconds, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.warn("等待关闭完成时被中断", e);
            Thread.currentThread().interrupt();
            return false;
        }
    }

    /**
     * 检查是否正在关闭
     * 
     * @return true如果正在关闭
     */
    public boolean isShuttingDown() {
        return isShuttingDown.get();
    }

    /**
     * 获取关闭状态信息
     * 
     * @return 关闭状态信息
     */
    public ShutdownStatus getShutdownStatus() {
        return new ShutdownStatus(
            isShuttingDown.get(),
            shutdownLatch.getCount() == 0,
            System.currentTimeMillis()
        );
    }

    /**
     * 关闭状态信息类
     */
    public static class ShutdownStatus {
        private final boolean isShuttingDown;
        private final boolean isShutdownComplete;
        private final long timestamp;

        public ShutdownStatus(boolean isShuttingDown, boolean isShutdownComplete, long timestamp) {
            this.isShuttingDown = isShuttingDown;
            this.isShutdownComplete = isShutdownComplete;
            this.timestamp = timestamp;
        }

        // Getter方法
        public boolean isShuttingDown() { return isShuttingDown; }
        public boolean isShutdownComplete() { return isShutdownComplete; }
        public long getTimestamp() { return timestamp; }

        @Override
        public String toString() {
            return String.format("ShutdownStatus{isShuttingDown=%s, isShutdownComplete=%s, timestamp=%d}",
                               isShuttingDown, isShutdownComplete, timestamp);
        }
    }
}
